package com.basker.pisces.springcloud.feign;

import java.util.function.Function;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.util.Assert;

import com.basker.pisces.spring.SpringApplicationContext;

/**
 * Feign的工具类
 *
 * @author hangwen
 */
public class FeignUtils {

    private static final Function<Object, Class<?>> FIND_FEIGNCLIENT_TYPE = (proxyObject) -> {
        Class<?>[] interfaces = null;
        try {
            interfaces = AopProxyUtils.proxiedUserInterfaces(proxyObject);
            if (ArrayUtils.isEmpty(interfaces)) {
                return null;
            }
        } catch (IllegalArgumentException e) {
            return null;
        }

        for (Class<?> inter : interfaces) {
            FeignClient feignClient = inter.getAnnotation(FeignClient.class);
            if (feignClient != null) {
                return inter;
            }
        }

        return null;
    };

    /**
     * 根据feignClient代理对象获取该对象对应的{@link FeignClient}注解
     *
     * @param proxy
     * @return
     */
    public static FeignClient getFeignClientAnnotation(Object proxyObject) {
        Class<?> type = getFeignClientType(proxyObject);
        return type != null ? type.getAnnotation(FeignClient.class) : null;
    }

    /**
     * 根据feignClient代理对象获取该对象对应的接口类型
     *
     * @param proxyObject
     * @return
     */
    public static Class<?> getFeignClientType(Object proxyObject) {
        return FIND_FEIGNCLIENT_TYPE.apply(proxyObject);
    }

    /**
     * 获取feignClient访问的服务端应用名
     *
     * @param feignClient
     * @return
     */
    public static String getServiceApplicationName(FeignClient feignClient) {
        Assert.notNull(feignClient, "parameter 'feignClient' is required");

        String name = feignClient.name();
        name = StringUtils.isEmpty(name) ? feignClient.value() : name;

        if (name.startsWith("${") && name.endsWith("}")) {
            name = SpringApplicationContext.getConfig().resolvePlaceholders(name);
        }

        return name;
    }

    /**
     * 获取feignClient访问的服务端应用名
     *
     * @param feignClient
     * @return
     */
    public static String getServiceApplicationName(Object proxyObject) {
        FeignClient annotation = getFeignClientAnnotation(proxyObject);
        return annotation != null ? getServiceApplicationName(annotation) : null;
    }
}
